import {
  AppStyleCollections,
  BODY_SELECTOR,
  BodyClasses,
  logger,
  MODULE_CONFIG,
} from '../types/constants'
import { PageHandler } from './page_handler'

interface IElementSelector {
  navbar: string
  scriptNavigator: string
}

export class ElementManager {
  private readonly name: string = 'ElementManager'
  private static instance: ElementManager
  // 展示列数
  readonly defaultMaxColumns: number = 4
  readonly defaultMinColumns: number = 1
  private isPrintColumn: boolean = false
  maxColumns: number = this.defaultMaxColumns // 最大可用列数
  maxColumnsUpdated: boolean = false
  // 加载页数
  readonly defaultMaxPageNum: number = 5
  maxPageNum: number = this.defaultMaxPageNum // 最大可用加载页数

  public static getInstance(): ElementManager {
    if (!ElementManager.instance) {
      ElementManager.instance = new ElementManager()
    }
    return ElementManager.instance
  }

  /**
   * 元素选择器
   */
  get selector(): IElementSelector {
    return {
      navbar: this.navbarSelector,
      scriptNavigator: this.ScriptNavigatorSelector,
    }
  }

  /**
   * 导航菜单栏选择器（未折叠状态）
   */
  get navbarSelector(): string {
    return `${BODY_SELECTOR}:has(nav.${MODULE_CONFIG.PLATFORM.greasyFork.navbarId}:not(.${BodyClasses.IS_COLLAPSED}))`
  }

  /**
   * 脚本导航栏选择器（非空）
   */
  get ScriptNavigatorSelector(): string {
    return `${BODY_SELECTOR}:has(${AppStyleCollections.Module.SCRIPT_NAVIGATOR.selector}:not(.${BodyClasses.IS_EMPTY}))`
  }

  /**
   * 检查导航菜单栏是否存在
   */
  isNavbarExist(): boolean {
    const $navbar = $(this.navbarSelector)

    return $navbar && $navbar.length > 0
  }

  /**
   * 获取导航菜单栏高度
   * @param format 高度格式，'px' 或 'number'
   * @param fallbackValue  fallbackValue 高度不存在时的回退值
   */
  getNavbarHeight(format: 'px' | 'number' = 'number', fallbackValue: number | string = 0): string | number {
    if (!this.isNavbarExist()) {
      return format === 'px' ? `${fallbackValue}px` : Number.parseFloat(fallbackValue.toString())
    }

    const rawHeight = MODULE_CONFIG.COMPONENTS.navbar.height
    const numericValue = typeof rawHeight === 'number'
      ? rawHeight
      : Number.parseFloat(rawHeight)

    if (Number.isNaN(numericValue)) {
      logger.warn(`[${this.name}] 无效的高度配置: ${rawHeight}, 使用默认值 ${fallbackValue}`)
      return format === 'px' ? `${fallbackValue}px` : fallbackValue
    }

    return format === 'px' ? `${numericValue}px` : numericValue
  }

  /**
   * 动态计算最大可用列数
   */
  calculateMaxColumns(): number {
    let pageConfig: { selector: string, container: string } | undefined

    if (this.maxColumnsUpdated)
      return this.maxColumns

    const page = PageHandler.getCurrentPageInstance()
    const pageType = PageHandler.getCurrentPageType()

    if (page && 'getResultSelectors' in page) {
      pageConfig = page.getResultSelectors?.(pageType as any, false)
    }

    if (!pageConfig)
      return this.defaultMaxColumns

    if (!pageConfig.container || !pageConfig.selector)
      return this.defaultMinColumns

    const container = document.querySelector(pageConfig.container)
    const sampleItem = document.querySelector(pageConfig.selector)

    if (!container || !sampleItem)
      return this.defaultMaxColumns

    const safeWidth = 70 // 缓冲值
    const itemWidth = this.getSafeWidth(sampleItem) + safeWidth
    const containerWidth = document.documentElement.clientWidth
    const screenWidth = window.innerWidth

    const containerBased = Math.floor(containerWidth / itemWidth)
    const screenBased = Math.floor(screenWidth / 300)
    const finalValue = Math.min(
      containerBased,
      screenBased,
      this.defaultMaxColumns,
    )

    if (!this.isPrintColumn) {
      this.isPrintColumn = true

      logger.attention(`[${this.name}] 动态计算最大可用列数: ${finalValue}`, {
        width: {
          containerWidth,
          screenWidth,
          itemWidth,
        },
        container: containerBased,
        screen: screenBased,
        default: this.defaultMaxColumns,
      })
    }

    if (!this.maxColumnsUpdated)
      this.maxColumns = finalValue

    this.maxColumnsUpdated = true

    return finalValue
  }

  /**
   * 安全计算元素宽度（不影响实际DOM）
   */
  private getSafeWidth = (el: Element | null): number => {
    if (!el)
      return 300 // 默认值

    const parent = el.parentElement as HTMLElement
    // 克隆元素（不包含子元素）
    const clone = el.cloneNode(false) as HTMLElement

    // 设置克隆样式
    Object.assign(clone.style, {
      visibility: 'hidden',
      width: '', // 清除可能的内联宽度
      height: 'auto',
      display: window.getComputedStyle(el).display,
    })

    // 添加到 DOM 但不可见
    parent.appendChild(clone)

    // 获取计算宽度
    const elementWidth = Math.round(clone.getBoundingClientRect().width)
    const width = Math.max(200, elementWidth)
    logger.info(`[${this.name}] 元素宽度: ${elementWidth}, 计算宽度: ${width}`)

    // 立即移除克隆
    parent.removeChild(clone)

    return width
  }
}
